29/10 Archivos de texto. Operaciones con cadenas de caracteres. String formaters. CLASE DE LABORATORIO (Gonzalo)
In [2]:
cadena_caracteres = "Hola mundo"
print dir(cadena_caracteres)
In [3]:
cadena_caracteres = 'Hola mundo'
print '"{0}" cambia a "{1}" con title'.format(cadena_caracteres, cadena_caracteres.title())
print '"{0}" cambia a "{1}" con lower'.format(cadena_caracteres, cadena_caracteres.lower())
print '"{0}" cambia a "{1} con upper"'.format(cadena_caracteres, cadena_caracteres.upper())
print '"{0}" cambia a "{1}" con capitalize'.format(cadena_caracteres, cadena_caracteres.capitalize())
print '"{0}" cambia a "{1}" cuando reemplazamos las o por 0'.format(cadena_caracteres, cadena_caracteres.replace('o', '0'))
Y también podemos separar y combinar strings:
In [4]:
print "Hola mundo".split()
print "Hola mundo".split('o')
print "Hola mundo".split('mu')
print ''.join(['Hola', 'mundo'])
print ' '.join(['Hola', 'mundo'])
var = '#separador#'.join(['Hola', 'mundo'])
var2 = var*2
print var2
Pero todo lo que vimos por el momento se guarda en memoria dinámica, por lo que al apagar la computadora, o simplemente con cerrar el programa y volver a abrirlo perdimos todos los datos que nos teníamos. La alternativa para esto siguen siendo los archivos.
Al igual que en C, en Python en el mismo momento que abrimos el archivo, se lo asignamos a uno físico y elegimos el modo de apertura, que si no le indicamos nada, tomará por defecto el de lectura.
El modo de apertura puede ser cualquier combinación de:
reset
de Pascal.rewrite
de Pascal. append
de Pascal.La primitiva del lenguaje para abrir y asignar un archivo es open, la cual puede recibir uno o dos parámetros. El primero es obligatorio, y corresponde a la ubicación relativa o absoluta del archivo físico. El segundo parámetro indica el modo de apertura y es opcional. Si no se lo pasamos asumirá que lo queremos abrir en modo Lectura.
Supongamos que estamos usando el intérprete en un escenario en el que solo tenemos un archivo que se llama f2.txt y queremos trabajar con los archivos f1.txt y f2.txt.
>>> # Lanza una excepción de IOError por no existir el archivo e
>>> # intentar abrirlo en modo lectura.
>>> file1 = open("f1.txt")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'f1.txt'
>>> # Intento abrir el archivo f1.txt, pero en modo escritura,
>>> # por lo crea y no falla. Si hubiera existido, lo hubiera
>>> # truncado y creado vacío.
>>> file1 = open("f1.txt", "w")
>>> # Abro el archivo f2.txt en modo lectura sin problemas, ya
>>> # que éste si existe.
>>> file2 = open("f2.txt")
Para cerrar un archivo solo tenemos que indicarlo poniendo la variable seguida de un punto y la primitiva close. La única restricción es que la variable sea de tipo archivo, si cerramos un archivo cerrado este sigue cerrado; y si cerramos uno abierto, el mismo cambia de estado.
>>> file2 = open("f2.txt") # Abro el archivo en modo lectura
>>> file2.close() # Cierro el archivo
Supongamos que tenemos un archivo llamado ejemplo.txt y tiene el siguiente texto:
Python was created in the early 1990s by Guido van Rossum at Stichting
Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
as a successor of a language called ABC. Guido remains Python's
principal author, although it includes many contributions from others.
In 1995, Guido continued his work on Python at the Corporation for
National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
in Reston, Virginia where he released several versions of the
software.
In May 2000, Guido and the Python core development team moved to
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
year, the PythonLabs team moved to Digital Creations (now Zope
Corporation, see http://www.zope.com). In 2001, the Python Software
Foundation (PSF, see http://www.python.org/psf/) was formed, a
non-profit organization created specifically to own Python-related
Intellectual Property. Zope Corporation is a sponsoring member of
the PSF.
All Python releases are Open Source (see http://www.opensource.org for
the Open Source Definition). Historically, most, but not all, Python
releases have also been GPL-compatible.
Para leer un archivo podemos usar la primitiva read, la cual puede recibir un parámetro que indique la cantidad de caracteres a leer. Si no se pasa ese parámetro el intérprete leerá todo el archivo y lo retornará.
In [ ]:
arch = open("ejemplo.txt")
cadena = arch.read(15)
print "# Imprimo los primeros 15 caracteres del archivo. Tiene que ser 'Python was crea'"
print cadena
print "# Leo otros 7 caracteres y dejo el cursor del archivo en la siguiente posición. Tiene que ser 'ted in '"
cadena = arch.read(7)
print cadena
print "# Ahora leo el resto del archivo."
cadena = arch.read()
print cadena
print '# Cierro el archivo'
arch.close()
La única condición que tenemos para usar este método es que el archivo lo hayamos abierto en modo lectura.
In [ ]:
arch2 = open("ejemplo2.txt", "w")
arch2.read()
In [ ]:
# Y si intentamos con un append?
arch3 = open("ejemplo1.txt", "a")
arch3.read()
Otra primitiva que podemos usar es readline, que al igual que read, también puede recibir un parámetro que indique la cantidad máxima de bytes a leer. Si no se le pasa ningún parámetro, lee toda la línea.
In [ ]:
arch = open("ejemplo.txt")
linea = arch.readline() # Notar que también imprime el Enter o \n
print linea
linea = arch.readline(7) # La segunda línea es 'Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands'
print linea
arch.close()
Pero no es necesario que leamos de a una sola línea, sino que también podemos leer todas las líneas del archivo y guardarlas en una lista haciendo uso de la primitiva readlines.
In [ ]:
arch = open("ejemplo.txt")
lineas = arch.readlines()
print lineas
arch.close()
Sin embargo, la forma más Pythonic de leer el archivo por líneas es usando la estructura for y quedaría casi como lo diríamos en castellano: "Para cada línea del archivo.
Por ejemplo, si queremos imprimir la cantidad de caracteres de cada línea podríamos hacer:
In [ ]:
arch = open("ejemplo.txt")
for linea in arch:
print len(linea)
arch.close()
Para escribir en un archivo podemos usar las las primitivas write(string) y writelines(lista_strings), que la primera es para escribir una cadena de caracteres y la segunda para escribir una lista de strings, uno a continuación del otro. Es importante destacar que en ningún caso se escribe algún carácter que no figure en los strings, como por ejemplo, caracteres de fin de línea.
El uso de writelines es equivalente a recorrer la lista y hacerle un write a cada elemento.
Pero el costo de escribir algo en el disco es mucho mayor a escribirlo en memoria por lo que, al igual que en C, se usa un buffer, que no es más que una porción de memoria para ir guardando en forma temporal los datos y cuando alcanzan un tamaño considerable se lo manda a escribir al disco. Otra forma de asegurarse que se haga la escritura es usando la primitiva flush, la cual guarda en el disco el contenido del buffer y lo vacía.
In [ ]:
arch2 = open("ejemplo2.txt", "w")
arch2.write("Es la primer cadena")
arch2.write("Seguida de la segunda con un fin de linea\n")
arch2.writelines(["1. Primero de la lista sin fin de línea. ", "2. Segundo string con fin de línea.\n", "3. Tercero con/\n.\n", "4. y último."])
arch2.flush()
arch2.close()
arch2 = open("ejemplo2.txt", "r+a")
strfile = arch2.read()
print strfile
¿Y qué pasa si le quiero agregar algunas líneas a este archivo?
In [ ]:
arch2.write("Esto lo estoy agregando.\n.")
arch2.writelines("Y estas dos líneas también con un \\n al final\n de cada una.\n")
arch2.flush()
arch2 = open("ejemplo2.txt", "r") # El open hace que me mueva a la primer posición del archivo.
print arch2.read()
arch2.close()
Otra forma de asegurarse que se escriba lo que hay en el disco es cerrándolo.
Al igual que en los archivos binarios de Pascal, en Python también podemos saltar a distintas posiciones mediante la primitiva seek(pos) la cual recibe, como mínimo un parámetro que indica la posición a la que nos queremos mover. Opcionalmente puede recibir un segundo parámetro:
In [ ]:
arch = open("ejemplo.txt")
arch.seek(30) # Voy a la posición número 30 del archivo
print arch.read(7) # Debería salir 'y 1990s'
arch.seek(-5,1) # Me muevo 5 posiciones para atrás desde mi posición actual.
print arch.read(7) # Debería imprimir '1990s b'
arch.seek(-12,2) # Me muevo a la posición número 12, comenzando a contar desde el final.
print arch.read(10) # Debería imprimir 'compatible'
arch.close()
Y así como podemos movernos en un archivo, también podemos averiguar nuestra posición usando la primitiva tell().
In [ ]:
arch = open("ejemplo.txt")
arch.seek(30)
print arch.tell() # Debería imprimir 30
arch.seek(-5,1) # Retrocedo 5 posiciones
print arch.tell() # Debería imprimir 25
arch.seek(-12,2) # Voy a 12 posiciones antes del fin de archivo
print arch.tell() # Debería imprimir 1132
print arch.read(10) # Leo 10 caracteres
print arch.tell() # Debería imprimir 1142
Leer un archivo de texto llamado curso.csv
en el que cada línea tendrá el siguiente formato:
padron,nombre,apellido,nota_parcial,nombre_de_grupo,nota_tp1,nota_tp2
Y resolver los mismos puntos que antes, pero contemplando que los alumnos ahora sólo tendrán una nota de parcial (la del último que hayan rendido).
Puede ocurrir que algunas líneas no cuenten con todos los campos, o que los campos numéricos no sean números, o que no pertenezcan al rango de 0 a 10. En dichos casos se deberán guardar esas líneas para mostrarlas una vez leído todo el archivo indicando que tienen algún error (no es necesario especificar cuál es el error).
Se pide:
Nota: 2
* nnnn1
* nnnn2
* nnnn3
* nnnn4
Nota: 4
* nnnn1
* nnnn2
...
Tener en cuenta que las notas pueden ser del 2 al 10 y puede ocurrir que nadie se haya sacado esa nota (y en dicho caso esa nota no tiene que aparecer en el listado)
In [ ]: